package controller

import (
	"background/config"
	"background/db"
	"background/model"
	"background/utils"
	"fmt"
	"image"
	"image/color"
	"image/gif"
	"image/jpeg"
	"io"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"os"
	"strconv"
	"strings"

	"github.com/disintegration/imaging"
	"github.com/gin-gonic/gin"
	json "github.com/json-iterator/go"
	"github.com/nfnt/resize"
	uuid "github.com/satori/go.uuid"

	// "github.com/nfnt/resize"
	// "image/jpeg"
	// "strings"

	"bufio"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"

	_ "golang.org/x/image/webp"
)

type FileController struct {
}

func (this *FileController) OnUploadDoc(c *gin.Context) {
	// uid, e := uuid.NewV1()
	// if nil != e {
	// 	log.Print(e.Error())
	// 	return
	// }
	// imgtype := c.Query("type")
	// log.Print(imgtype)
	// file, _, err := c.Request.FormFile("doc")
	// if nil != err || nil == file {
	// 	log.Print(err.Error())
	// 	return
	// }

	// img, name, err := image.Decode(file)
	// if nil != err {
	// 	log.Print(err.Error())
	// 	return
	// }
	// dx := img.Bounds().Dx()
	// // resize to width 1000 using Lanczos resampling
	// // and preserve aspect ratio
	// if dx > 800 {
	// 	dx = dx / 2
	// }
	// m := resize.Resize(uint(dx), 0, img, resize.Lanczos3)

	// datout, err := os.Create("image/" + uid.String() + "." + name)
	// defer datout.Close()
	// if err != nil {
	// 	log.Fatal(err)
	// }
	// jpeg.Encode(datout, m, nil)
	// c.JSON(200, map[string]interface{}{"url": uid.String() + "." + name})

}

func DownloadImg(imgUrl, filePath string) {

	res, err := http.Get(imgUrl)
	if err != nil {
		fmt.Println("A error occurred!")
		return
	}
	defer res.Body.Close()
	// 获得get请求响应的reader对象
	reader := bufio.NewReaderSize(res.Body, 32*1024)

	file, err := os.Create(filePath)
	if err != nil {
		panic(err)
	}
	// 获得文件的writer对象
	writer := bufio.NewWriter(file)
	written, _ := io.Copy(writer, reader)
	fmt.Printf("Total length: %d", written)
	file.Close()
}

func (this *FileController) OnUpaloadPic(c *gin.Context) {
	uid, e := uuid.NewV1()
	if nil != e {
		log.Print(e.Error())
		return
	}
	type Url struct {
		Url string `json:"url"`
	}
	var url Url

	e = c.BindJSON(&url)
	if nil != e {
		log.Print(e.Error())
		return
	}
	DownloadImg(url.Url, "image/"+uid.String()+".png")

	c.JSON(200, map[string]interface{}{"url": uid.String() + ".png"})
}

func (this *FileController) OnUpload(c *gin.Context) {
	uid, e := uuid.NewV1()
	if nil != e {
		log.Print(e.Error())
		return
	}
	imgtype := c.Query("type")
	log.Print(imgtype)
	file, _, err := c.Request.FormFile("image")
	if nil != err || nil == file {
		log.Print(err.Error())
		return
	}

	if imgtype == "gif" {
		allgifs, er := gif.DecodeAll(file)
		if nil != er {
			log.Print("decode error", er.Error())
			return
		}

		datout, err := os.Create("image/" + uid.String() + ".gif")
		defer datout.Close()
		if err != nil {
			log.Fatal(err)
			return
		}

		gif.EncodeAll(datout, allgifs)
		c.JSON(200, map[string]interface{}{"url": uid.String() + ".gif"})
	} else {
		img, name, err := image.Decode(file)
		log.Print("image type is", name)

		if nil != err {
			log.Print(err.Error())
			return
		}
		dx := img.Bounds().Dx()
		// resize to width 1000 using Lanczos resampling
		// and preserve aspect ratio
		if dx > 800 {
			dx = dx / 2
		}
		m := resize.Resize(uint(dx), 0, img, resize.Lanczos3)

		datout, err := os.Create("image/" + uid.String() + "." + name)
		defer datout.Close()
		if err != nil {
			log.Fatal(err)
		}
		jpeg.Encode(datout, m, nil)
		c.JSON(200, map[string]interface{}{"url": uid.String() + "." + name})
	}
}

func (this *FileController) OnUploadOrigin(c *gin.Context) {
	uid, e := uuid.NewV1()
	if nil != e {
		log.Print(e.Error())
		return
	}
	imgtype := c.Query("type")
	file, _, err := c.Request.FormFile("image")
	if nil != err || nil == file {
		log.Print(err.Error())
		return
	}

	if imgtype == "gif" {
		allgifs, er := gif.DecodeAll(file)
		if nil != er {
			log.Print("decode error", er.Error())
			return
		}

		datout, err := os.Create("image/" + uid.String() + ".gif")
		defer datout.Close()
		if err != nil {
			log.Fatal(err)
			return
		}

		gif.EncodeAll(datout, allgifs)
		c.JSON(200, map[string]interface{}{"url": uid.String() + ".gif"})
	} else {
		img, name, err := image.Decode(file)
		if nil != err {
			log.Print(err.Error())
			return
		}
		dx := img.Bounds().Dx()
		// resize to width 1000 using Lanczos resampling
		// and preserve aspect ratio

		m := resize.Resize(uint(dx), 0, img, resize.Lanczos3)

		datout, err := os.Create("image/" + uid.String() + "." + name)
		defer datout.Close()
		if err != nil {
			log.Fatal(err)
		}
		jpeg.Encode(datout, m, nil)
		c.JSON(200, map[string]interface{}{"url": uid.String() + "." + name})
	}
}

func (this *FileController) FileList(c *gin.Context) {
	var nodes utils.FileDesc
	path := c.Query("path")
	utils.GetPathFileName("files\\"+path, &nodes)
	log.Print(nodes)
	bs, e := json.Marshal(nodes)
	if nil != e {
		log.Print(e.Error())
	}
	log.Print(string(bs))
	c.JSON(200, map[string]interface{}{
		"msg":    "ok",
		"status": 200,
		"files":  nodes,
	})
}

func (this *FileController) FileType(c *gin.Context) {

}

func (this *FileController) DownloadFile(c *gin.Context) {
	resp := RespBase{Msg: "FAIL", Status: 211}
	filename := c.Query("filename")
	file, e := os.Open("files//" + filename)
	if nil != e {
		log.Print(e.Error())
		c.JSON(200, resp)
		return
	}
	bytes, e := ioutil.ReadAll(file)
	if nil != e {
		log.Print(e.Error())
		c.JSON(200, resp)
		return
	}
	c.Header("X-Content-Type-Options", "nosniff")
	c.Header("Content-Disposition",
		"/files/"+filename)
	c.Writer.Write(bytes)

}
func myAtoi(str string) int {
	num := 0
	s := ""
	flag := false
	str = strings.TrimSpace(str)
	if len(str) == 0 {
		return 0
	}
	for i := 0; i < len(str); i++ {
		if !(str[i] >= '0' && str[i] <= '9') && !(str[i] == '+' || str[i] == '-') {
			break
		}
		if str[i] == '+' {
			if flag || s != "" {
				break
			}
			flag = true
			continue
		}
		if str[i] == '-' {
			if flag || s != "" {
				break
			}
			flag = true
			s += "-"
			continue
		}
		s += string(str[i])
	}
	num, _ = strconv.Atoi(s)
	if num > math.MaxInt32 {
		return math.MaxInt32
	} else if num < math.MinInt32 {
		return math.MinInt32
	}
	return num
}

func (this *FileController) OnFileUploadFileMarkdown(c *gin.Context) {
	parent := c.Query("parent")
	filename := c.Query("filename")
	file, _, err := c.Request.FormFile("file")
	if nil != err || nil == file {
		log.Print(err.Error())
		return
	}
	bytes, err := ioutil.ReadAll(file)
	if nil != err {
		log.Print(err.Error())
		return
	}
	log.Print(parent, filename, string(bytes))

	query := fmt.Sprintf("select * from doc_copy1 where doc_copy1.id = '%d'", int32(myAtoi(parent)))
	docs := []model.DocTree{}
	e := db.GetMysqlClient().Query2(query, &docs)
	if nil != e {
		log.Print(e.Error())
		return
	}
	if len(docs) == 0 {
		return
	}

	fork := strings.ReplaceAll(string(bytes), "\\\\", "\\\\\\\\")
	fork = strings.ReplaceAll(string(fork), "\\", "\\\\")

	e = model.CreateDocTree(
		model.DocTree{
			Title:    filename,
			Content:  fork,
			Author:   "admin",
			IsPublic: 1,
			Father:   int32(myAtoi(parent)),
			Level:    docs[0].Level + 1,
		},
	)
	if nil != e {
		log.Printf(e.Error())
	}
	c.JSON(200, map[string]interface{}{"msg": "ok"})
}

func (this *FileController) OnFileUploadFile(c *gin.Context) {
	path := c.Query("path")
	filename := c.Query("filename")
	file, _, err := c.Request.FormFile("file")
	if nil != err || nil == file {
		log.Print(err.Error())
		return
	}
	bytes, err := ioutil.ReadAll(file)
	if nil != err {
		log.Print(err.Error())
		return
	}
	header := make([]byte, 512)
	copy(header, bytes)
	types := http.DetectContentType(header)
	log.Print(types)
	// jpg
	defer file.Close()
	out, err := os.Create("files/" + path + "/" + filename)
	if err != nil {
		log.Print(err)
	}
	defer out.Close()
	out.Write(bytes)
	log.Print(len(bytes))
	c.JSON(200, map[string]interface{}{"msg": "ok"})
}

func (this *FileController) OnThumbnail(c *gin.Context) {
	resp := RespBase{Msg: "FAIL", Status: 211}

	fileName := c.Param("file")
	if "" == fileName {
		c.JSON(200, resp)

		return
	}
	// input files
	files := []string{"/home/ubuntu/api/bin/image/" + fileName}

	// load images and make 100x100 thumbnails of them
	var thumbnails []image.Image
	for _, file := range files {
		img, err := imaging.Open(file)
		if err != nil {
			panic(err)
		}
		thumb := imaging.Thumbnail(img, 100, 100, imaging.CatmullRom)
		thumbnails = append(thumbnails, thumb)
	}

	// create a new blank image
	dst := imaging.New(100*len(thumbnails), 100, color.NRGBA{0, 0, 0, 0})

	// paste thumbnails into the new image side by side
	for i, thumb := range thumbnails {
		dst = imaging.Paste(dst, thumb, image.Pt(i*100, 0))
	}

	// save the combined image to file
	err := imaging.Save(dst, "/home/ubuntu/api/bin/image/thumbnail_"+fileName)
	if err != nil {
		log.Print(err.Error())
		return
	}
	// open file
	file, e := os.Open("/home/ubuntu/api/bin/image/thumbnail_" + fileName)
	if nil != e {
		log.Print(e.Error())
		c.JSON(200, resp)

		return
	}
	defer file.Close()
	bytes, e := ioutil.ReadAll(file)
	if nil != e {
		log.Print(e.Error())
		c.JSON(200, resp)

		return
	}
	c.Header("X-Content-Type-Options", "nosniff")
	c.Header("Content-Type", "image/png")
	c.Header("Content-Disposition",
		"/image/"+fileName)
	c.Writer.Write(bytes)
}

func (this *FileController) OnDownLoad(c *gin.Context) {
	resp := RespBase{Msg: "FAIL", Status: 211}

	fileName := c.Param("file")
	if "" == fileName {
		c.JSON(200, resp)

		return
	}
	if config.ApiConfig().PicServer == 1 {
		file, e := os.Open(utils.GetCurrentDirectory() + "/image/" + fileName)

		if nil != e {
			log.Print(e.Error())
			c.JSON(200, resp)

			return
		}
		defer file.Close()
		bytes, e := ioutil.ReadAll(file)
		if nil != e {
			log.Print(e.Error())
			c.JSON(200, resp)

			return
		}
		c.Header("X-Content-Type-Options", "nosniff")
		c.Header("Content-Type", "image/png")
		c.Header("Content-Disposition",
			"/image/"+fileName)
		c.Writer.Write(bytes)
	} else {
		res, err := http.Get("http://hdrtc.net:4596/api/image_download/" + fileName)
		if err != nil {
			log.Print(err.Error())
			return
		}
		defer res.Body.Close()
		// 获得get请求响应的reader对象
		reader := bufio.NewReaderSize(res.Body, 32*1024)
		// 创建文件对象
		bytes, e := ioutil.ReadAll(reader)
		if nil != e {
			log.Print(e.Error())
			c.JSON(200, resp)
			return
		}
		c.Header("X-Content-Type-Options", "nosniff")
		c.Header("Content-Type", "image/png")
		c.Header("Content-Disposition",
			"/image/"+fileName)
		c.Writer.Write(bytes)

	}

}
